//=============================================================================
//
// MotorEx_2M_Master.cpp : "Extended motor control mode with two motors
//                         on Master"
//
// This example continuously starts two synchronized motors with changing
// rotation directions. Motors are connected to outputs M1 and M2. Pulses from
// the motors are calculated by the counters C1 and C2. The motors are stopped
// and rotation direction is changed after both counters reach the value of 200.
//
//-----------------------------------------------------------------------------
// Disclaimer - Exclusion of Liability
//
// This software is distributed in the hope that it will be useful,but WITHOUT 
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
// FITNESS FOR A PARTICULAR PURPOSE. It can be used an modified by anyone
// free of any license obligations or authoring rights.
//=============================================================================

#include "StdAfx.h"

#define TA_IDX                  TA_LOCAL
#define MASTER_MOTOR_NUMBER     1
#define MASTER_MOTOR_IDX        (MASTER_MOTOR_NUMBER - 1)
#define SLAVE_MOTOR_NUMBER      2
#define SLAVE_MOTOR_IDX         (SLAVE_MOTOR_NUMBER - 1)

static BOOL32 rotation_direction;
static BOOL32 prev_rotation_direction;
static DWORD motor_pos_reached;

#define MOTOR_ON        TRUE
#define MOTOR_OFF       FALSE

#define STRMAXLEN       80

HANDLE  fthdl;
DWORD   errCode;
char    ComPortName[STRMAXLEN];
char    LibVersion[STRMAXLEN];


//=============================================================================

/*-----------------------------------------------------------------------------
 *  MotorExReached callback  
 *---------------------------------------------------------------------------*/
void __stdcall cbMotorExReached(DWORD shmId, DWORD mIdx)
{
    motor_pos_reached += (mIdx + 1);
}

/*-----------------------------------------------------------------------------
 *  MotorEx_2M_Master  
 *---------------------------------------------------------------------------*/
static void MotorEx_2M_Master(void) {

    //  configure master motor output to be used as a motor output
    SetFtMotorConfig(fthdl, TA_IDX, MASTER_MOTOR_IDX, MOTOR_ON);

    //  configure slave motor output to be used as a motor output
    SetFtMotorConfig(fthdl, TA_IDX, SLAVE_MOTOR_IDX, MOTOR_ON);

    rotation_direction = FALSE;
    prev_rotation_direction = !rotation_direction;

    //  set callback function for "motor reached position" event
    SetCBMotorExReached(cbMotorExReached);

    while (1) {
        if (rotation_direction != prev_rotation_direction) {

            motor_pos_reached = 0;

            //  start extended motor control command:
            //  motor should run with slave motor until counter reaches 200
            StartMotorExCmd(fthdl, TA_IDX, MASTER_MOTOR_IDX, DUTY_MAX, rotation_direction,
                SLAVE_MOTOR_IDX, rotation_direction, 200);

            prev_rotation_direction = rotation_direction;
        }

        //  if both motors have reached position
        if (motor_pos_reached == MASTER_MOTOR_NUMBER + SLAVE_MOTOR_NUMBER) {

            rotation_direction = !rotation_direction;
        }

        Sleep(10);
    }
}

/*-----------------------------------------------------------------------------
 *  CheckParameter  
 *---------------------------------------------------------------------------*/
static int CheckCOMPar(int argc, char *argv[]) {

    char    *pStr;
    int     comNo;

    if (argc >= 2) {
        if (strlen(argv[1]) > 3) {
            if ((pStr=strstr(argv[1],"COM")) != NULL) {
                sscanf(pStr+3, "%d", &comNo);
                if (comNo >= 1 && comNo <= 255)
                    return 0;
                else {
                    cout << "MotorEx_2M_Master.exe: invalid COM number..." << endl << endl;
                    return 1;
                }
            }
        }
    }

    cout << "MotorEx_2M_Master.exe: no input given..." << endl << endl;
    return 1;
}

/*-----------------------------------------------------------------------------
 *  main
 *  
 *---------------------------------------------------------------------------*/
int main(int argc, char *argv[]) {

    cout << "\nExample MotorEx_2M_Master.exe ..." << endl;

    //  check input paramter
    if (CheckCOMPar(argc,argv)) {
        cout << "Usage: MotorEx_2M_Master.exe COMxx\t(e.g. COM2 or COM32)" << endl;
        return 1;
    }

    //  get library version
    ftxGetLibVersionStr(LibVersion, STRMAXLEN);
    cout << "\nftMscLib " << LibVersion << endl;

    //  library initialization
    errCode = ftxInitLib();

    strcpy(ComPortName, argv[1]);
    cout << "\nOpen ComPort '" << ComPortName << "' ..." << endl;

    //  open COM port
    fthdl = ftxOpenComDevice(ComPortName, 38400, &errCode);

    if (errCode == FTLIB_ERR_SUCCESS) {

        cout << "Connected to ROBO TX Controller ..." << endl;

        //  starting Transfer Area
        errCode = ftxStartTransferArea(fthdl);

        if (errCode == FTLIB_ERR_SUCCESS) {

            cout << "Transfer Area was started and runs..." << endl;

            MotorEx_2M_Master();

            //  stop Transfer Area
            ftxStopTransferArea(fthdl);
        }

        else {
            //  error case
            cout << "Error: Transfer Area was not started !" << endl;
        }

        //  closing port
        cout << "Closing ComPort '" << ComPortName << "' ..." << endl;
        errCode = ftxCloseDevice(fthdl);
    }

    else {
        //  error case
        cout << "Error: No interface available (Port '" << ComPortName << "')" << endl;
    }

    //  close library
    ftxCloseLib();

    return 0;
}
